home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / rules / stubs / stubraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  13.2 KB  |  486 lines

  1. /*========================================================================
  2.  *
  3.  * FILE:
  4.  * stubraw.c
  5.  *
  6.  * IDENTIFICATION:
  7.  * $Header: /private/postgres/src/rules/stubs/RCS/stubraw.c,v 1.12 1991/08/08 16:07:14 sp Exp $
  8.  *
  9.  * DESCRIPTION:
  10.  *
  11.  * Routines that transform a 'Prs2RawStub' to a 'Prs2Stub' and vice versa.
  12.  *
  13.  *========================================================================
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include "tmp/postgres.h"
  18. #include "parser/parse.h"       /* for the AND, NOT, OR */
  19. #include "utils/log.h"
  20. #include "rules/prs2.h"
  21. #include "rules/prs2stub.h"
  22. #include "tmp/datum.h"
  23. #include "nodes/primnodes.h"
  24. #include "nodes/primnodes.a.h"
  25.  
  26. extern Const RMakeConst();
  27. extern Param RMakeParam();
  28. extern LispValue StringToPlan();
  29.  
  30.  
  31. /*-----------------------------------------------------------------------
  32.  *
  33.  * prs2StubToRawStub
  34.  *
  35.  * given a 'Prs2Stub' (which is a spaghetti of pointers)
  36.  * transform it to a stream of bytes suitable for disk storage
  37.  *
  38.  *-----------------------------------------------------------------------
  39.  */
  40. Prs2RawStub
  41. prs2StubToRawStub(relstub)
  42. Prs2Stub relstub;
  43. {
  44.     Prs2RawStub *pieces, res;
  45.     int npieces;
  46.     int maxsize;
  47.     int i;
  48.  
  49.     maxsize = 1000000000;
  50.     pieces = prs2StubToSmallRawStubs(relstub, maxsize, &npieces);
  51.     if (npieces != 1) {
  52.     elog(WARN, "Hey! this is a pretty hefty stub you've got there!");
  53.     }
  54.  
  55.     res = pieces[0];
  56.     pfree(pieces);
  57.  
  58.     return(res);
  59. }
  60.  
  61. /*-----------------------------------------------------------------------
  62.  *
  63.  * prs2StubToSmallRawStubs
  64.  *
  65.  * Similar to 'prs2StubToRawStub' but if the resulting stub is too big,
  66.  * then it breaks it in many pieces, each one of them being
  67.  * less than 'maxSize' bytes long.
  68.  * It returns an array of 'Prs2RawStub'. This array has '*nStubPiecesP'
  69.  * entries.
  70.  *
  71.  * THE ECOLOGICAL MESSAGE OF THE WEEK:
  72.  * Do not waste memory, recycle it! So, don't forget to pfree the stubs
  73.  * and the array when you are done!
  74.  *-----------------------------------------------------------------------
  75.  */
  76. Prs2RawStub *
  77. prs2StubToSmallRawStubs(relstub, maxSize, nStubPiecesP)
  78. Prs2Stub relstub;
  79. int *nStubPiecesP;
  80. {
  81.     Size thisSize, headerSize, sumSizes, locksize;
  82.     int nPieces;
  83.     Prs2RawStub *res;
  84.     Prs2OneStub oneStub;
  85.     char **stubQual;
  86.     int *stubSizes;
  87.     int i,j;
  88.     int len;
  89.     char *s;
  90.     int nstubs;
  91.  
  92.     /*
  93.      * NOTE: this routine does a two pass "parsing" of 'relstub'.
  94.      * The first one to find the size needed for the raw stub
  95.      * representation and the second to actually store the information.
  96.      * However as in order to complete the first step we must 
  97.      * transform the stub qualifications to strings and then repeat
  98.      * this process again during the second pass and as this takes
  99.      * quite some time, we instead opt to store the strings
  100.      * (the ascii reperesentations) of the stubs quals in an array
  101.      * during the first pass so we do not have to recalculate them 
  102.      * during the second!)
  103.      */
  104.     if (relstub->numOfStubs>0) {
  105.     stubQual = (char **)palloc(sizeof(char *) * relstub->numOfStubs);
  106.     if (stubQual == NULL) {
  107.         elog(WARN, "prs2StubToRawStub: Out of memory!\n");
  108.     }
  109.     stubSizes = (int *)palloc(sizeof(int) * relstub->numOfStubs);
  110.     if (stubSizes == NULL) {
  111.         elog(WARN, "prs2StubToRawStub: Out of memory!\n");
  112.     }
  113.     } else {
  114.     stubQual = NULL;
  115.     stubSizes = NULL;
  116.     }
  117.  
  118.     /*
  119.      * calculate the number of bytes needed to hold
  120.      * the raw representation of this stub record.
  121.      * First we calculate the # of bytes needed for
  122.      * each individual `Prs2OneStub' and we store it
  123.      * in array 'stubSizes'
  124.      */
  125.  
  126.     for (i=0; i< relstub->numOfStubs; i++) {
  127.     /*
  128.      * calculate the size of each individual `Prs2OneStub'
  129.      * Start with the fixed size part of the struct.
  130.      */
  131.     oneStub = relstub->stubRecords[i];
  132.     thisSize = sizeof(oneStub->ruleId) +
  133.         sizeof(oneStub->stubId) +
  134.         sizeof(oneStub->counter);
  135.     /*
  136.      * now add the rule lock size
  137.      */
  138.     thisSize = thisSize +
  139.         prs2LockSize( prs2GetNumberOfLocks(oneStub->lock));
  140.     /*
  141.      * finally add the size of the stub's qualification.
  142.      * NOTE: we store it a string preceded by an integer
  143.      * holding its length.
  144.      * Don't forget to store this string to an array
  145.      * so that we don't have to recalculate it later.
  146.      */
  147.     s = lispOut(oneStub->qualification);
  148.     stubQual[i] = s;
  149.     thisSize = thisSize + (strlen(s) + sizeof(int));
  150.     /*
  151.      * store the size to 'stubSizes' and also
  152.      * add it to the total size
  153.      */
  154.     stubSizes[i] = thisSize;
  155.  
  156.     }
  157.  
  158.     /*
  159.      * calculate in how many pieces we have to break
  160.      * the stub so that each piece is less than 'maxSize'
  161.      * bytes long.
  162.      *
  163.      * NOTE: Just as like in the "varlena" structure, the "size" field
  164.      * in the Prs2RawStubData is the sum of its own size + the (variable)
  165.      * size of the data that is following.
  166.      */
  167.     nPieces = 0;
  168.     headerSize = sizeof(res[0]->vl_len) + sizeof(relstub->numOfStubs);
  169.     sumSizes = headerSize;
  170.     for (i=0; i< relstub->numOfStubs; i++) {
  171.     if (sumSizes + stubSizes[i] > maxSize) {
  172.         nPieces++;
  173.         sumSizes = stubSizes[i] + headerSize;
  174.     } else {
  175.         sumSizes = sumSizes + stubSizes[i];
  176.     }
  177.     }
  178.     nPieces++;
  179.  
  180.     /*
  181.      * OK, allocate an array of that many raw stub pieces
  182.      */
  183.     res = (Prs2RawStub *) palloc(sizeof(Prs2RawStub) * nPieces);
  184.     if (res==NULL) {
  185.     elog(WARN,"prs2StubToRawStub: Out of memory");
  186.     }
  187.  
  188.     /*
  189.      * Now allocate enough space for each 
  190.      * such piece
  191.      */
  192.     j=0;
  193.     sumSizes = headerSize;
  194.     for (i=0; i< relstub->numOfStubs; i++) {
  195.     if (sumSizes + stubSizes[i] > maxSize) {
  196.         res[j] = (Prs2RawStub)palloc(sumSizes);
  197.         if (res[j]==NULL) {
  198.         elog(WARN,"prs2StubToRawStub: Out of memory");
  199.         }
  200.         res[j]->vl_len = sumSizes;
  201.         j++;
  202.         sumSizes = stubSizes[i] + headerSize;
  203.     } else {
  204.         sumSizes = sumSizes + stubSizes[i];
  205.     }
  206.     }
  207.     res[j] = (Prs2RawStub)palloc(sumSizes);
  208.     if (res[j]==NULL) {
  209.     elog(WARN,"prs2StubToRawStub: Out of memory");
  210.     }
  211.     res[j]->vl_len = sumSizes;
  212.  
  213.     
  214.     /*
  215.      * now copy the stubs to the raw stub pieces.
  216.      */
  217.     j=0;
  218.     s = &(res[j]->vl_dat[0]) + sizeof(relstub->numOfStubs);
  219.     sumSizes = headerSize;
  220.     nstubs = 0;
  221.  
  222.  
  223.     for (i=0; i< relstub->numOfStubs; i++) {
  224.     if (sumSizes + stubSizes[i] > maxSize) {
  225.         /*
  226.          * time to start a new piece...
  227.          * first update the 'numOfStubs' field of the previous
  228.          * piece
  229.          */
  230.         bcopy((char *) &nstubs, &(res[j]->vl_dat[0]), sizeof(nstubs));
  231.         /*
  232.          * now continue with the next stub
  233.          */
  234.         j++;
  235.         s = &(res[j]->vl_dat[0]) + sizeof(relstub->numOfStubs);
  236.         sumSizes = headerSize;
  237.         nstubs = 0;
  238.     }
  239.     sumSizes = sumSizes + stubSizes[i];
  240.     nstubs ++;
  241.     /*
  242.      * copy this prs2OneStub to the raw stub piece
  243.      */
  244.     oneStub = relstub->stubRecords[i];
  245.     /*
  246.      * copy the fixed size part of the record
  247.      */
  248.     bcopy((char *)&(oneStub->ruleId), s, sizeof(oneStub->ruleId));
  249.     s += sizeof(oneStub->ruleId);
  250.     bcopy((char *)&(oneStub->stubId), s, sizeof(oneStub->stubId));
  251.     s += sizeof(oneStub->stubId);
  252.     bcopy((char *)&(oneStub->counter), s, sizeof(oneStub->counter));
  253.     s += sizeof(oneStub->counter);
  254.     /*
  255.      * now copy the rule lock
  256.      */
  257.     locksize = prs2LockSize(prs2GetNumberOfLocks(oneStub->lock));
  258.     bcopy((char *) oneStub->lock, s, locksize);
  259.     s+=locksize;
  260.     /*
  261.      * finally copy the qualification
  262.      * First the length of the string and then the string itself.
  263.      */
  264.     len = strlen(stubQual[i]);
  265.     bcopy((char *) &len, s, sizeof(int));
  266.     s += sizeof(int);
  267.     bcopy(stubQual[i], s, len);
  268.     s += len;
  269.     }
  270.     /*
  271.      * Don't forget to update the 'numOfStubs' field of the
  272.      * last piece!
  273.      */
  274.     bcopy((char *) &nstubs, &(res[j]->vl_dat[0]), sizeof(nstubs));
  275.  
  276.     /*
  277.      * Keep POSTGRES memory clean!
  278.      */
  279.     for (i=0; i< relstub->numOfStubs; i++) {
  280.     pfree(stubQual[i]);
  281.     }
  282.     if (relstub->numOfStubs > 0) {
  283.     pfree(stubQual);
  284.     pfree(stubSizes);
  285.     }
  286.  
  287.     /* 
  288.      * OK we are done!
  289.      */
  290.     *nStubPiecesP = nPieces;
  291.     return(res);
  292. }
  293.  
  294. /*----------------------------------------------------------------------
  295.  *
  296.  * prs2RawStubToStub
  297.  *
  298.  * given a stream of bytes (like the one created by
  299.  * 'prs2StubToRawStub') recreate the original stub record
  300.  *
  301.  *----------------------------------------------------------------------
  302.  */
  303. Prs2Stub
  304. prs2RawStubToStub(rawStub)
  305. Prs2RawStub rawStub;
  306. {
  307.     Prs2Stub relstub;
  308.     Prs2OneStub oneStub;
  309.     Size size;
  310.     int i,j;
  311.     int len;
  312.     char *data;
  313.     char *s;
  314.     Prs2LocksData ruleLock;
  315.  
  316.     /*
  317.      * create a new stub record
  318.      */
  319.     relstub = prs2MakeStub();
  320.     if (relstub == NULL) {
  321.     elog(WARN, "prs2RawStubToStub: Out of memory");
  322.     }
  323.  
  324.     /*
  325.      * copy the number of individual stub records
  326.      */
  327.     data = VARDATA(rawStub);
  328.     bcopy(data, (char *)&(relstub->numOfStubs), sizeof(relstub->numOfStubs));
  329.     data += sizeof(relstub->numOfStubs);
  330.  
  331.     /*
  332.      * allocate space for the `relstub->numOfStubs' records of
  333.      *type 'Prs2OneStubData'
  334.      */
  335.     if (relstub->numOfStubs > 0 ) {
  336.     size = relstub->numOfStubs * sizeof(Prs2OneStub);
  337.     relstub->stubRecords = (Prs2OneStub *) palloc(size);
  338.     if (relstub->stubRecords == NULL) {
  339.         elog(WARN, "prs2RawStubToStub: Out of memory");
  340.     }
  341.     } else {
  342.     relstub->stubRecords = NULL;
  343.     }
  344.     
  345.     for (i=0; i< relstub->numOfStubs; i++) {
  346.     oneStub = prs2MakeOneStub();
  347.     relstub->stubRecords[i] = oneStub;
  348.     /*
  349.      * copy the fixed part of the 'Prs2OneStub' first.
  350.      */
  351.         bcopy(data, (char *)&(oneStub->ruleId), sizeof(oneStub->ruleId));
  352.         data += sizeof(oneStub->ruleId);
  353.         bcopy(data, (char *)&(oneStub->stubId), sizeof(oneStub->stubId));
  354.         data += sizeof(oneStub->stubId);
  355.         bcopy(data, (char *)&(oneStub->counter), sizeof(oneStub->counter));
  356.         data += sizeof(oneStub->counter);
  357.  
  358.     /*
  359.      * now copy the rule lock
  360.      * XXX: NOTE:
  361.      * In order to copy the rule lock, we have to find its
  362.      * size. But in order to find its size we must read
  363.      * the 'numberOfLocks' field.
  364.      * We can not just cast 'data' to a RuleLock because
  365.      * of alignment problems, so we must copy it.
  366.      */
  367.     bcopy(data, (char *) &ruleLock,
  368.         sizeof(Prs2LocksData)-sizeof(Prs2OneLockData));
  369.     size = prs2LockSize(prs2GetNumberOfLocks(&ruleLock));
  370.     oneStub->lock = (RuleLock) palloc(size);
  371.     if (oneStub->lock == NULL) {
  372.         elog(WARN, "prs2RawStubToStub: Out of memory");
  373.     }
  374.     bcopy(data, (char*)(oneStub->lock), size);
  375.     data += size;
  376.  
  377.     /*
  378.      * now recreate the qualification (which is stored
  379.      * as a string containing the ascii representation
  380.      * of a LispValue).
  381.      * First read the length of the string & then 
  382.      * create the LispValue out of the string.
  383.      */
  384.     bcopy(data, (char*)&len, sizeof(int));
  385.     data += sizeof(int);
  386.     oneStub->qualification = StringToPlan(data);
  387.     data += len;
  388.     }
  389.  
  390.     /*
  391.      * At last! we are done...
  392.      */
  393.     return(relstub);
  394. }
  395.  
  396. /*----------------------------------------------------------------------
  397.  * prs2RawStubUnion
  398.  *
  399.  * Make and return the union of the two given raw stubs.
  400.  *----------------------------------------------------------------------
  401.  */
  402. Prs2RawStub
  403. prs2RawStubUnion(stub1, stub2)
  404. Prs2RawStub stub1;
  405. Prs2RawStub stub2;
  406. {
  407.     Prs2RawStub res;
  408.     int size, size1, size2;
  409.     int nstubs, nstubs1, nstubs2;
  410.     char *data1, *data2;
  411.     char *s;
  412.  
  413.     /*
  414.      * the data of each stub consists of the 4 bytes used
  415.      * to store the number of the "small stub record" (i.e.
  416.      * the equivalent to 'Prs2OneStubData' structure) contained
  417.      * in this stub + the data for these "small stub records".
  418.      * All this data is stored in the "vl_dat" field.
  419.      *
  420.      * Note that the number stored in "vl_len" is the size of all
  421.      * this stuff + the size of the "vl_len" field itself.
  422.      *
  423.      * The size of data  of the union will be the sum of space needed
  424.      * for the "small stub records" for stub 1, the space
  425.      * needed for the "small stub records" of stub2 and
  426.      * finally the 4 bytes to store the total number of
  427.      * new "small stub records".
  428.      */
  429.  
  430.     /*
  431.      * read the 'number of stubs' information into 'nstubs1'
  432.      * and make 'data1' point to the first "small stub record"
  433.      * 'size1' is the size of the information for the "small
  434.      * stub records" only.
  435.      */
  436.     s = &(stub1->vl_dat[0]);
  437.     bcopy(s, (char *) &nstubs1, sizeof(nstubs1));
  438.     data1 = s + sizeof(nstubs1);
  439.     size1 = stub1->vl_len - sizeof(stub1->vl_len) - sizeof(nstubs1);
  440.  
  441.     /*
  442.      * same thing for stub 2
  443.      */
  444.     s = &(stub2->vl_dat[0]);
  445.     bcopy(s, (char *) &nstubs2, sizeof(nstubs2));
  446.     data2 = s + sizeof(nstubs2);
  447.     size2 = stub2->vl_len - sizeof(stub2->vl_len) - sizeof(nstubs2);
  448.  
  449.     /*
  450.      * find the total number of stubs and calculate the
  451.      * total size of the their union (including the number of
  452.      * small stub records and the size of 'vl_len')
  453.      */
  454.     nstubs = nstubs1 + nstubs2;
  455.     size = size1 + size2 + sizeof(nstubs) + sizeof(res->vl_len);
  456.  
  457.  
  458.     /*
  459.      * allocate space for the new stub and copy there the
  460.      * information about the number of stubs
  461.      */
  462.     res = (Prs2RawStub) palloc(size);
  463.     if (res == NULL) {
  464.     elog(WARN,"prs2RawStubUnion: Out of memory");
  465.     }
  466.     res->vl_len = size;
  467.     s = &(res->vl_dat[0]);
  468.     bcopy((char *)&nstubs, s, sizeof(nstubs));
  469.  
  470.     /*
  471.      * now concatenate the data for the small stub records of
  472.      * stub1 and stub2 and copy them in the new union stub
  473.      */
  474.     s += sizeof(nstubs);
  475.     bcopy(data1, s, size1);
  476.     s += size1;
  477.     bcopy(data2, s, size2);
  478.  
  479.     /*
  480.      * OK, we are done...
  481.      */
  482.     return(res);
  483. }
  484.  
  485.  
  486.